﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using YJKGeometryFuncs;
using YJKRevitDimensionText.DimCreator;
using YJKRevitDimensionText.OneKeyPlanDim.DimesionDataEx;
using YJKRevitDimensionText.OneKeyPlanDim.Utility;

namespace YJKRevitDimensionText.OneKeyPlanDim.InWallDim
{
	public class DrawInWallDWDim
	{
		public List<ElementId> DimCrossWall
		{
			get
			{
				return this.m_lstDimCrossWallId;
			}
		}

		public DrawInWallDWDim(Autodesk.Revit.DB.Document doc, BaseDataOper baseData)
		{
			this.m_doc = doc;
			this.m_isDimOutWall = false;
			this.m_lstGridGroup = new List<GridGroupDataEx>();
			this.m_lstInWallData = new List<WallDataEx>();
			this.m_lstOutWallData = new List<WallDataEx>();
			this.m_lstOutOpeningId = new List<ElementId>();
			this.m_lstDimCrossWallId = new List<ElementId>();
			if (baseData != null)
			{
				this.m_lstGridGroup.AddRange(baseData.GetAllParallelGrid());
				this.m_lstInWallData.AddRange(baseData.GetInWallData());
			}
		}

		public DrawInWallDWDim(Autodesk.Revit.DB.Document doc, BaseDataOper baseData, List<WallDataEx> lstOutWall, List<ElementId> lstOutOpeningId)
		{
			this.m_doc = doc;
			this.m_isDimOutWall = true;
			this.m_lstGridGroup = new List<GridGroupDataEx>();
			this.m_lstInWallData = new List<WallDataEx>();
			this.m_lstOutWallData = new List<WallDataEx>();
			this.m_lstOutOpeningId = new List<ElementId>();
			this.m_lstDimCrossWallId = new List<ElementId>();
			if (baseData != null)
			{
				this.m_lstGridGroup.AddRange(baseData.GetAllParallelGrid());
				this.m_lstOutWallData.AddRange(lstOutWall);
				this.m_lstOutOpeningId.AddRange(lstOutOpeningId);
			}
		}

		public void DrawDim()
		{
			if (this.m_lstInWallData.Count < 1 && this.m_lstOutWallData.Count < 1)
			{
				return;
			}
			this.m_lstLeaderDim = new List<LeaderDimension>();
			foreach (List<WallDataEx> lstWallData in this.GroupWallData())
			{
				if (this.GroupWallIntersectGrid(lstWallData))
				{
					this.DimGroupWallWidthGrid(lstWallData);
				}
				else
				{
					this.DimGroupWallWidthoutGrid(lstWallData);
				}
			}
			List<Dimension> list = new List<Dimension>();
			this.m_lstDimCrossWallId.Clear();
			foreach (LeaderDimension leaderDim in this.m_lstLeaderDim)
			{
				this.CreateOpeningGroupDim(leaderDim, ref list);
			}
			foreach (Dimension inputDim in list)
			{
				DimAvoidManager.ClearCache();
				DimAvoidManager.TryAutoAvoidForHorizontal(this.m_doc, inputDim);
			}
			DimAvoidManager.TryAutoAvoidElementForHorizontal(this.m_doc, list);
		}

		private void DimGroupWallWidthGrid(List<WallDataEx> lstWallData)
		{
			List<OpeningDimItem> list = new List<OpeningDimItem>();
			this.GetOpeningDimWithGrid(lstWallData, list);
			if (list.Count < 1)
			{
				return;
			}
			Line line = lstWallData[0].ProfileLine as Line;
			this.ResetDimPoints(list, line);
			DrawInWallDWDim.SortOpeningDims(list, line.Direction);
			while (list.Count > 0)
			{
				List<OpeningDimItem> list2 = new List<OpeningDimItem>();
				OpeningDimItem openingDimItem = list[0];
				list2.Add(openingDimItem);
				list.RemoveAt(0);
				this.GroupOpeningDimWidthGrid(openingDimItem.GridLines, list, list2);
				XYZ openingDimVector = this.GetOpeningDimVector(list2);
				double openingsMaxSideWidth = this.GetOpeningsMaxSideWidth(list2, openingDimVector);
				double openingHostMaxSideWidth = this.GetOpeningHostMaxSideWidth(list2, openingDimVector);
				double dSizeLineOffset = Math.Max(openingsMaxSideWidth, openingHostMaxSideWidth) + DrawInWallDWDim.m_dSizeLineOffset;
				this.ReCheckOpeningGridLines(list2);
				List<XYZ> list3 = new List<XYZ>();
				foreach (OpeningDimItem openingDimItem2 in list2)
				{
					list3.Add(openingDimItem2.DimPoint1);
					list3.Add(openingDimItem2.DimPoint2);
				}
				this.ClearOverlapPoint(list3);
				DrawInWallDWDim.SortPoints(list3, line.Direction);
				XYZ xyz = list3.First<XYZ>();
				XYZ xyz2 = list3.Last<XYZ>();
				Line line2 = Line.CreateBound(xyz, xyz2);
				foreach (OpeningDimItem openingDimItem3 in list2)
				{
					foreach (Line line3 in openingDimItem3.GridLines)
					{
						Line line4 = DimPublicFunc.ChangeLineElevation(line3, xyz.Z);
						XYZ xyz3 = Geometry.IntersectWithTwoCurves(line2, line4, xyz, true, false, null);
						if (xyz3 != null)
						{
							list3.Add(xyz3);
						}
					}
				}
				DrawInWallDWDim.SortPoints(list3, line2.Direction);
				this.ClearOverlapPoint(list3);
				LeaderDimension item = new LeaderDimension(true, dSizeLineOffset, openingDimVector, list3);
				this.m_lstLeaderDim.Add(item);
			}
		}

		private void DimGroupWallWidthoutGrid(List<WallDataEx> lstWallData)
		{
			List<OpeningDimItem> list = new List<OpeningDimItem>();
			this.GetOpeningDimWithoutGrid(lstWallData, list);
			Line line = lstWallData[0].ProfileLine as Line;
			this.ResetDimPoints(list, line);
			DrawInWallDWDim.SortOpeningDims(list, line.Direction);
			while (list.Count > 0)
			{
				List<OpeningDimItem> list2 = new List<OpeningDimItem>();
				OpeningDimItem openingDimItem = list[0];
				list2.Add(openingDimItem);
				list.RemoveAt(0);
				this.GroupOpeningDimWidthWall(openingDimItem.WallLine, list, list2);
				XYZ openingDimVector = this.GetOpeningDimVector(list2);
				double openingsMaxSideWidth = this.GetOpeningsMaxSideWidth(list2, openingDimVector);
				double openingHostMaxSideWidth = this.GetOpeningHostMaxSideWidth(list2, openingDimVector);
				double dSizeLineOffset = Math.Max(openingsMaxSideWidth, openingHostMaxSideWidth) + DrawInWallDWDim.m_dSizeLineOffset;
				List<XYZ> list3 = new List<XYZ>();
				foreach (OpeningDimItem openingDimItem2 in list2)
				{
					list3.Add(openingDimItem2.DimPoint1);
					list3.Add(openingDimItem2.DimPoint2);
				}
				DrawInWallDWDim.SortPoints(list3, line.Direction);
				XYZ xyz = list3.First<XYZ>();
				XYZ xyz2 = list3.Last<XYZ>();
				this.ClearOverlapPoint(list3);
				List<XYZ> list4 = new List<XYZ>();
				foreach (OpeningDimItem openingDimItem3 in list2)
				{
					XYZ item = Geometry.CalculateFootPoint(xyz, xyz2, openingDimItem3.WallLine.GetEndPoint(0));
					XYZ item2 = Geometry.CalculateFootPoint(xyz, xyz2, openingDimItem3.WallLine.GetEndPoint(1));
					list4.Add(item);
					list4.Add(item2);
				}
				DrawInWallDWDim.SortPoints(list4, line.Direction);
				XYZ ptNewDim = list4.First<XYZ>();
				XYZ ptNewDim2 = list4.Last<XYZ>();
				this.GetNearWallSidePoint(list3.First<XYZ>(), list3.Last<XYZ>(), openingDimVector, ref ptNewDim, ref ptNewDim2);
				this.AddDimPoint(ptNewDim, list3);
				this.AddDimPoint(ptNewDim2, list3);
				LeaderDimension item3 = new LeaderDimension(false, dSizeLineOffset, openingDimVector, list3);
				this.m_lstLeaderDim.Add(item3);
			}
		}

		private void GetNearWallSidePoint(XYZ ptOpening1, XYZ ptOpening2, XYZ vtDim, ref XYZ ptWall1, ref XYZ ptWall2)
		{
			XYZ xyz = (ptOpening1 - ptOpening2).Normalize();
			XYZ xyz2 = (ptWall1 - ptWall2).Normalize();
			if (!Geometry.IsEqual(xyz, xyz2))
			{
				XYZ xyz3 = ptWall1;
				ptWall1 = ptWall2;
				ptWall2 = xyz3;
			}
			if (!Geometry.Is_Point_OnSegment(ptOpening1, ptOpening2, ptWall1, DrawInWallDWDim.m_dPointOverlapDist))
			{
				XYZ nearWallSidePoint = this.GetNearWallSidePoint(ptOpening1, ptWall1, vtDim);
				if (nearWallSidePoint != null)
				{
					ptWall1 = nearWallSidePoint;
				}
			}
			if (!Geometry.Is_Point_OnSegment(ptOpening1, ptOpening2, ptWall2, DrawInWallDWDim.m_dPointOverlapDist))
			{
				XYZ nearWallSidePoint2 = this.GetNearWallSidePoint(ptOpening2, ptWall2, vtDim);
				if (nearWallSidePoint2 != null)
				{
					ptWall2 = nearWallSidePoint2;
				}
			}
		}

		private XYZ GetNearWallSidePoint(XYZ ptDim1, XYZ ptDim2, XYZ vtDim)
		{
			double num = AssistFunc.mmToFeet(250.0);
			XYZ xyz = ptDim1 + vtDim * num;
			XYZ xyz2 = ptDim2 + vtDim * num;
			Line dimLine = Line.CreateBound(xyz, xyz2);
			List<XYZ> list = this.LineCrossWallSide(dimLine, this.m_lstInWallData, false);
			if (list != null && list.Count > 0)
			{
				XYZ nearPoint = this.GetNearPoint(xyz, list);
				XYZ xyz3 = (xyz - xyz2).Normalize();
				XYZ xyz4 = (nearPoint - xyz2).Normalize();
				if (Geometry.IsEqual(xyz3, xyz4))
				{
					return Geometry.CalculateFootPoint(ptDim1, ptDim2, nearPoint);
				}
			}
			List<WallDataEx> wallDataAtPoint = this.GetWallDataAtPoint(ptDim2, AssistFunc.mmToFeet(300.0));
			if (wallDataAtPoint.Count > 2)
			{
				return null;
			}
			num = AssistFunc.mmToFeet(5.0);
			xyz = ptDim1 - vtDim * num;
			xyz2 = ptDim2 - vtDim * num;
			dimLine = Line.CreateBound(xyz, xyz2);
			list = this.LineCrossWallSide(dimLine, wallDataAtPoint, true);
			if (list != null && list.Count > 0)
			{
				XYZ farPoint = this.GetFarPoint(xyz, list);
				XYZ xyz5 = (xyz2 - xyz).Normalize();
				XYZ xyz6 = (farPoint - xyz2).Normalize();
				if (Geometry.IsEqual(xyz5, xyz6))
				{
					return Geometry.CalculateFootPoint(ptDim1, ptDim2, farPoint);
				}
			}
			return null;
		}

		private XYZ GetNearPoint(XYZ ptBase, List<XYZ> lstPoint)
		{
			XYZ xyz = null;
			double num = double.MaxValue;
			foreach (XYZ xyz2 in lstPoint)
			{
				double num2 = ptBase.DistanceTo(xyz2);
				if (xyz == null || num2 < num)
				{
					xyz = xyz2;
					num = num2;
				}
			}
			return xyz;
		}

		private XYZ GetFarPoint(XYZ ptBase, List<XYZ> lstPoint)
		{
			XYZ xyz = null;
			double num = 0.0;
			foreach (XYZ xyz2 in lstPoint)
			{
				double num2 = ptBase.DistanceTo(xyz2);
				if (xyz == null || num2 > num)
				{
					xyz = xyz2;
					num = num2;
				}
			}
			return xyz;
		}

		private List<XYZ> LineCrossWallSide(Line dimLine, List<WallDataEx> lstWallData, bool bMustCrossFullWall)
		{
			XYZ endPoint = dimLine.GetEndPoint(0);
			List<XYZ> list = new List<XYZ>();
			foreach (WallDataEx wallDataEx in lstWallData)
			{
				Line line = wallDataEx.InLine as Line;
				Line line2 = wallDataEx.OutLine as Line;
				if (!(line == null) && !(line2 == null) && DimPublicFunc.IsVertical(dimLine.Direction, line.Direction))
				{
					line = DimPublicFunc.ChangeLineElevation(line, endPoint.Z);
					line2 = DimPublicFunc.ChangeLineElevation(line2, endPoint.Z);
					XYZ xyz = Geometry.IntersectWithTwoCurves(dimLine, line, endPoint, false, false, null);
					XYZ xyz2 = Geometry.IntersectWithTwoCurves(dimLine, line2, endPoint, false, false, null);
					if (xyz != null || xyz2 != null)
					{
						if (bMustCrossFullWall)
						{
							if (xyz == null)
							{
								xyz = Geometry.IntersectWithTwoCurves(dimLine, line, endPoint, true, false, null);
							}
							if (xyz2 == null)
							{
								xyz2 = Geometry.IntersectWithTwoCurves(dimLine, line2, endPoint, true, false, null);
							}
						}
						if (xyz != null)
						{
							list.Add(xyz);
						}
						if (xyz2 != null)
						{
							list.Add(xyz2);
						}
					}
				}
			}
			return list;
		}

		private void CreateOpeningGroupDim(LeaderDimension leaderDim, ref List<Dimension> lstDim)
		{
			List<XYZ> dimPositions = leaderDim.DimPositions;
			XYZ xyz = dimPositions.First<XYZ>() + leaderDim.DimVector * leaderDim.SizeLineOffset;
			XYZ xyz2 = dimPositions.Last<XYZ>() + leaderDim.DimVector * leaderDim.SizeLineOffset;
			Line sizeLine = Line.CreateBound(xyz, xyz2);
			List<ElementId> list = this.DimSizeLineCrossWall(sizeLine, leaderDim.WidthGrid, dimPositions);
			if (list != null && list.Count > 0)
			{
				this.m_lstDimCrossWallId.AddRange(list);
			}
			this.CreateLeaderDim(sizeLine, dimPositions, leaderDim.DimVector, ref lstDim);
		}

		private void CreateLeaderDim(Line sizeLine, List<XYZ> lstDimPoint, XYZ vtDim, ref List<Dimension> lstDim)
		{
			if (lstDimPoint.Count < 2)
			{
				return;
			}
			Transaction transaction = new Transaction(this.m_doc);
			transaction.Start("CreateCurve");
			double num = AssistFunc.mmToFeet(1.0);
			ReferenceArray referenceArray = new ReferenceArray();
			try
			{
				foreach (XYZ xyz in lstDimPoint)
				{
					Line line = Line.CreateBound(xyz, xyz + vtDim * num);
					DetailCurve detailCurve = this.m_doc.Create.NewDetailCurve(this.m_doc.ActiveView, line);
					referenceArray.Append(detailCurve.GeometryCurve.Reference);
				}
				transaction.Commit();
			}
			catch
			{
				transaction.RollBack();
				return;
			}
			Dimension dimension = new SizeDimData(this.m_doc, sizeLine, referenceArray).CreateDim(false);
			if (dimension != null)
			{
				lstDim.Add(dimension);
			}
		}

		private List<ElementId> DimSizeLineCrossWall(Line sizeLine, bool bDimWidthGrid, List<XYZ> lstDimPoint)
		{
			XYZ ptNewDim = null;
			XYZ ptNewDim2 = null;
			List<ElementId> list = new List<ElementId>();
			foreach (WallDataEx wallDataEx in this.m_lstInWallData)
			{
				if (this.LineCrossWall(sizeLine, wallDataEx, bDimWidthGrid, ref ptNewDim, ref ptNewDim2) && !this.LineCrossWallOpening(sizeLine, wallDataEx))
				{
					list.Add(wallDataEx.WallId);
					this.AddDimPoint(ptNewDim, lstDimPoint);
					this.AddDimPoint(ptNewDim2, lstDimPoint);
				}
			}
			return list;
		}

		private bool LineCrossWall(Line crossLine, WallDataEx wallData, bool bDimWidthGrid, ref XYZ ptInterIn, ref XYZ ptInterOut)
		{
			Line line = wallData.InLine as Line;
			Line line2 = wallData.OutLine as Line;
			if (line == null || line2 == null)
			{
				return false;
			}
			if (!DimPublicFunc.IsVertical(crossLine.Direction, line.Direction))
			{
				return false;
			}
			XYZ endPoint = crossLine.GetEndPoint(0);
			XYZ endPoint2 = crossLine.GetEndPoint(1);
			line = DimPublicFunc.ChangeLineElevation(line, endPoint.Z);
			line2 = DimPublicFunc.ChangeLineElevation(line2, endPoint.Z);
			ptInterIn = Geometry.IntersectWithTwoCurves(crossLine, line, endPoint, false, false, null);
			ptInterOut = Geometry.IntersectWithTwoCurves(crossLine, line2, endPoint, false, false, null);
			if (ptInterIn != null && (Geometry.IsEqual(ptInterIn, endPoint, DrawInWallDWDim.m_dPointOverlapDist) || Geometry.IsEqual(ptInterIn, endPoint2, DrawInWallDWDim.m_dPointOverlapDist)))
			{
				return false;
			}
			if (ptInterOut != null && (Geometry.IsEqual(ptInterOut, endPoint, DrawInWallDWDim.m_dPointOverlapDist) || Geometry.IsEqual(ptInterOut, endPoint2, DrawInWallDWDim.m_dPointOverlapDist)))
			{
				return false;
			}
			if (ptInterIn == null && ptInterOut == null)
			{
				return false;
			}
			if (bDimWidthGrid)
			{
				if (ptInterIn == null)
				{
					ptInterIn = Geometry.IntersectWithTwoCurves(crossLine, line, endPoint, true, true, null);
				}
				if (ptInterOut == null)
				{
					ptInterOut = Geometry.IntersectWithTwoCurves(crossLine, line2, endPoint, true, true, null);
				}
			}
			else if (ptInterIn == null || ptInterOut == null)
			{
				return false;
			}
			return true;
		}

		private bool DimGroupCrossOpening(List<OpeningDimItem> lstOpeningDimGroup)
		{
			XYZ openingDimVector = this.GetOpeningDimVector(lstOpeningDimGroup);
			double openingsMaxSideWidth = this.GetOpeningsMaxSideWidth(lstOpeningDimGroup, openingDimVector);
			double openingHostMaxSideWidth = this.GetOpeningHostMaxSideWidth(lstOpeningDimGroup, openingDimVector);
			double num = Math.Max(openingsMaxSideWidth, openingHostMaxSideWidth) + DrawInWallDWDim.m_dSizeLineOffset;
			List<XYZ> list = new List<XYZ>();
			foreach (OpeningDimItem openingDimItem in lstOpeningDimGroup)
			{
				list.Add(openingDimItem.DimPoint1);
				list.Add(openingDimItem.DimPoint2);
			}
			XYZ direction = lstOpeningDimGroup[0].WallLine.Direction;
			DrawInWallDWDim.SortPoints(list, direction);
			XYZ xyz = list.First<XYZ>() + openingDimVector * num;
			XYZ xyz2 = list.Last<XYZ>() + openingDimVector * num;
			Line line = Line.CreateBound(xyz, xyz2);
			foreach (WallDataEx wallDataEx in this.m_lstInWallData)
			{
				Line line2 = wallDataEx.ProfileLine as Line;
				if (!(line2 == null))
				{
					if (!DimPublicFunc.IsVertical(line.Direction, line2.Direction))
					{
						return false;
					}
					if (this.LineCrossWallOpening(line, wallDataEx))
					{
						return true;
					}
				}
			}
			return false;
		}

		private bool LineCrossWallOpening(Line crossLine, WallDataEx wallData)
		{
			XYZ endPoint = crossLine.GetEndPoint(0);
			foreach (DoorWinDataEx doorWinDataEx in wallData.WallWindows)
			{
				if (!(doorWinDataEx.doorWinLine == null))
				{
					Line line = DimPublicFunc.ChangeLineElevation(doorWinDataEx.doorWinLine, endPoint.Z);
					if (Geometry.IntersectWithTwoCurves(crossLine, line, endPoint, false, false, null) != null)
					{
						return true;
					}
				}
			}
			return false;
		}

		private void AddDimPoint(XYZ ptNewDim, List<XYZ> lstDimPoint)
		{
			XYZ xyz = lstDimPoint.First<XYZ>();
			XYZ xyz2 = lstDimPoint.Last<XYZ>();
			XYZ xyz3 = (xyz2 - xyz).Normalize();
			XYZ xyz4 = Geometry.CalculateFootPoint(xyz, xyz2, ptNewDim);
			for (int i = 0; i < lstDimPoint.Count; i++)
			{
				if (Geometry.LessThan(xyz4.DistanceTo(lstDimPoint[i]), DrawInWallDWDim.m_dPointOverlapDist))
				{
					return;
				}
				XYZ xyz5 = (xyz4 - lstDimPoint[i]).Normalize();
				if (!Geometry.IsEqual(xyz3, xyz5))
				{
					lstDimPoint.Insert(i, xyz4);
					return;
				}
			}
			lstDimPoint.Add(xyz4);
		}

		private XYZ GetOpeningDimVector(List<OpeningDimItem> lstOpeningDimGroup)
		{
			XYZ wallOutDirection = lstOpeningDimGroup[0].WallOutDirection;
			if (this.m_isDimOutWall)
			{
				return wallOutDirection;
			}
			foreach (OpeningDimItem openingDimItem in lstOpeningDimGroup)
			{
				if (openingDimItem.IsDimDoor)
				{
					return openingDimItem.DimDirection;
				}
			}
			return wallOutDirection;
		}

		private double GetOpeningsMaxSideWidth(List<OpeningDimItem> lstOpeningDimGroup, XYZ vtSide)
		{
			double num = 0.0;
			foreach (OpeningDimItem openingDimItem in lstOpeningDimGroup)
			{
				double val = 0.0;
				if (DimPublicFunc.GetOpeningSideWidth(this.m_doc, openingDimItem.Opening, openingDimItem.DimPoint1, vtSide, ref val))
				{
					num = Math.Max(num, val);
				}
			}
			return num;
		}

		private double GetOpeningHostMaxSideWidth(List<OpeningDimItem> lstOpeningDimGroup, XYZ vtSide)
		{
			double num = 0.0;
			foreach (OpeningDimItem openingDimItem in lstOpeningDimGroup)
			{
				Line line = openingDimItem.HostWall.InLine as Line;
				Line line2 = openingDimItem.HostWall.OutLine as Line;
				if (!(line == null) && !(line2 == null))
				{
					XYZ dimPoint = openingDimItem.DimPoint1;
					XYZ xyz = dimPoint + vtSide * 10.0;
					Line line3 = Line.CreateBound(dimPoint, xyz);
					line = DimPublicFunc.ChangeLineElevation(line, dimPoint.Z);
					line2 = DimPublicFunc.ChangeLineElevation(line2, dimPoint.Z);
					XYZ xyz2 = Geometry.IntersectWithTwoCurves(line3, line, dimPoint, true, true, null);
					XYZ xyz3 = Geometry.IntersectWithTwoCurves(line3, line2, dimPoint, true, true, null);
					if (xyz2 != null && xyz3 != null)
					{
						double num2 = dimPoint.DistanceTo(xyz2);
						if (!Geometry.IsEqual(vtSide, (xyz2 - dimPoint).Normalize()))
						{
							num2 *= -1.0;
						}
						double num3 = dimPoint.DistanceTo(xyz3);
						if (!Geometry.IsEqual(vtSide, (xyz3 - dimPoint).Normalize()))
						{
							num3 *= -1.0;
						}
						double val = Math.Max(num2, num3);
						num = Math.Max(num, val);
					}
				}
			}
			return num;
		}

		private void ClearOverlapPoint(List<XYZ> lstPoint)
		{
			for (int i = 0; i < lstPoint.Count - 1; i++)
			{
				XYZ xyz = lstPoint[i];
				int num = i + 1;
				while (num < lstPoint.Count && !Geometry.LessThan(DrawInWallDWDim.m_dPointOverlapDist, xyz.DistanceTo(lstPoint[num])))
				{
					lstPoint.RemoveAt(num);
					num--;
					num++;
				}
			}
		}

		private void GroupOpeningDimWidthGrid(List<Line> lstGridLine1, List<OpeningDimItem> lstOpeningDim, List<OpeningDimItem> lstOpeningDimGroup)
		{
			if (lstOpeningDim.Count < 1)
			{
				return;
			}
			OpeningDimItem openingDimItem = lstOpeningDim[0];
			List<Line> gridLines = openingDimItem.GridLines;
			if (this.IsGroupGridLines(lstGridLine1, gridLines))
			{
				lstOpeningDimGroup.Add(openingDimItem);
				if (this.DimGroupCrossOpening(lstOpeningDimGroup))
				{
					lstOpeningDimGroup.RemoveAt(lstOpeningDimGroup.Count - 1);
					return;
				}
				lstOpeningDim.RemoveAt(0);
				this.GroupOpeningDimWidthGrid(gridLines, lstOpeningDim, lstOpeningDimGroup);
			}
		}

		private void GroupOpeningDimWidthWall(Line wallLine, List<OpeningDimItem> lstOpeningDim, List<OpeningDimItem> lstOpeningDimGroup)
		{
			if (lstOpeningDim.Count < 1)
			{
				return;
			}
			OpeningDimItem openingDimItem = lstOpeningDim[0];
			Line wallLine2 = openingDimItem.WallLine;
			if (this.IsSameLine(wallLine, wallLine2))
			{
				lstOpeningDimGroup.Add(openingDimItem);
				lstOpeningDim.RemoveAt(0);
				this.GroupOpeningDimWidthWall(wallLine, lstOpeningDim, lstOpeningDimGroup);
				return;
			}
			if (this.IsLinkLine(wallLine, wallLine2))
			{
				lstOpeningDimGroup.Add(openingDimItem);
				lstOpeningDim.RemoveAt(0);
				this.GroupOpeningDimWidthWall(wallLine2, lstOpeningDim, lstOpeningDimGroup);
			}
		}

		private void ResetDimPoints(List<OpeningDimItem> lstOpeningDim, Line wallLine)
		{
			double num = 0.0;
			if (this.m_doc.ActiveView.GenLevel != null)
			{
				num = this.m_doc.ActiveView.GenLevel.Elevation;
			}
			foreach (OpeningDimItem openingDimItem in lstOpeningDim)
			{
				XYZ xyz = Geometry.CalculateFootPoint(wallLine, openingDimItem.DimPoint1);
				openingDimItem.DimPoint1 = new XYZ(xyz.X, xyz.Y, num);
				XYZ xyz2 = Geometry.CalculateFootPoint(wallLine, openingDimItem.DimPoint2);
				openingDimItem.DimPoint2 = new XYZ(xyz2.X, xyz2.Y, num);
			}
		}

		private void ReCheckOpeningGridLines(List<OpeningDimItem> lstOpeningDimGroup)
		{
			if (lstOpeningDimGroup == null || lstOpeningDimGroup.Count < 1)
			{
				return;
			}
			if (lstOpeningDimGroup.Count == 1)
			{
				if (lstOpeningDimGroup[0].GridLines.Count > 1)
				{
					this.GetNearestGridLine(lstOpeningDimGroup[0]);
				}
				return;
			}
			OpeningDimItem openingDimItem = lstOpeningDimGroup[0];
			OpeningDimItem openingDimItem2 = lstOpeningDimGroup[lstOpeningDimGroup.Count - 1];
			XYZ xyz = Geometry.CalculatMidPoint(openingDimItem.DimPoint1, openingDimItem.DimPoint2);
			XYZ xyz2 = Geometry.CalculatMidPoint(openingDimItem2.DimPoint1, openingDimItem2.DimPoint2);
			XYZ xyz3 = Geometry.CalculatMidPoint(xyz, xyz2);
			Line line = Line.CreateBound(xyz, xyz2);
			if (openingDimItem.GridLines.Count == 2)
			{
				Line line2 = DimPublicFunc.ChangeLineElevation(openingDimItem.GridLines[0], xyz3.Z);
				Line line3 = DimPublicFunc.ChangeLineElevation(openingDimItem.GridLines[1], xyz3.Z);
				XYZ xyz4 = Geometry.IntersectWithTwoCurves(line, line2, xyz3, true, false, null);
				XYZ xyz5 = Geometry.IntersectWithTwoCurves(line, line3, xyz3, true, false, null);
				if (xyz4.DistanceTo(xyz3) < xyz5.DistanceTo(xyz3))
				{
					openingDimItem.GridLines.RemoveAt(1);
				}
				else
				{
					openingDimItem.GridLines.RemoveAt(0);
				}
			}
			if (openingDimItem2.GridLines.Count == 2)
			{
				Line line4 = DimPublicFunc.ChangeLineElevation(openingDimItem2.GridLines[0], xyz3.Z);
				Line line5 = DimPublicFunc.ChangeLineElevation(openingDimItem2.GridLines[1], xyz3.Z);
				XYZ xyz6 = Geometry.IntersectWithTwoCurves(line, line4, xyz3, true, false, null);
				XYZ xyz7 = Geometry.IntersectWithTwoCurves(line, line5, xyz3, true, false, null);
				if (xyz6.DistanceTo(xyz3) < xyz7.DistanceTo(xyz3))
				{
					openingDimItem2.GridLines.RemoveAt(1);
					return;
				}
				openingDimItem2.GridLines.RemoveAt(0);
			}
		}

		private void GetNearestGridLine(OpeningDimItem dimItem)
		{
			Line line = Line.CreateBound(dimItem.DimPoint1, dimItem.DimPoint2);
			XYZ xyz = Geometry.CalculatMidPoint(dimItem.DimPoint1, dimItem.DimPoint2);
			double num = double.MaxValue;
			Line line2 = null;
			foreach (Line line3 in dimItem.GridLines)
			{
				Line line4 = DimPublicFunc.ChangeLineElevation(line3, xyz.Z);
				XYZ xyz2 = Geometry.IntersectWithTwoCurves(line, line4, xyz, true, false, null);
				if (xyz2 != null)
				{
					double num2 = xyz2.DistanceTo(xyz);
					if (line2 == null || Geometry.LessThan(num2, num))
					{
						line2 = line3;
						num = num2;
					}
				}
			}
			if (line2 != null)
			{
				dimItem.GridLines.Clear();
				dimItem.GridLines.Add(line2);
			}
		}

		private void GetOpeningDimWithGrid(List<WallDataEx> lstWallData, List<OpeningDimItem> lstOpeningDim)
		{
			foreach (WallDataEx wallDataEx in lstWallData)
			{
				Line wallLine = wallDataEx.ProfileLine as Line;
				foreach (DoorWinDataEx doorWinDataEx in wallDataEx.WallWindows)
				{
					if (!(doorWinDataEx.doorWinLine == null) && (!wallDataEx.IsOutWall || this.m_lstOutOpeningId.Contains(doorWinDataEx.DWId)))
					{
						OpeningDimItem openingDim = this.GetOpeningDim(doorWinDataEx);
						if (openingDim.GridLines != null && openingDim.GridLines.Count > 0)
						{
							openingDim.WallLine = wallLine;
							openingDim.HostWall = wallDataEx;
							openingDim.WallOutDirection = wallDataEx.VecOutWall;
							lstOpeningDim.Add(openingDim);
						}
					}
				}
			}
		}

		private void GetOpeningDimWithoutGrid(List<WallDataEx> lstWallData, List<OpeningDimItem> lstOpeningDim)
		{
			foreach (WallDataEx wallDataEx in lstWallData)
			{
				Line wallLine = wallDataEx.ProfileLine as Line;
				foreach (DoorWinDataEx doorWinDataEx in wallDataEx.WallWindows)
				{
					Line doorWinLine = doorWinDataEx.doorWinLine;
					if (!(doorWinLine == null) && (!wallDataEx.IsOutWall || this.m_lstOutOpeningId.Contains(doorWinDataEx.DWId)))
					{
						lstOpeningDim.Add(new OpeningDimItem
						{
							DimPoint1 = doorWinLine.GetEndPoint(0),
							DimPoint2 = doorWinLine.GetEndPoint(1),
							DimDirection = doorWinDataEx.vecdoorWin.Negate(),
							WallLine = wallLine,
							HostWall = wallDataEx,
							WallOutDirection = wallDataEx.VecOutWall,
							IsDimDoor = doorWinDataEx.IsDoor,
							Opening = doorWinDataEx.WDInstance
						});
					}
				}
			}
		}

		private OpeningDimItem GetOpeningDim(DoorWinDataEx openingData)
		{
			Line doorWinLine = openingData.doorWinLine;
			List<Line> openingDimGridLine = this.GetOpeningDimGridLine(doorWinLine);
			return new OpeningDimItem
			{
				DimPoint1 = doorWinLine.GetEndPoint(0),
				DimPoint2 = doorWinLine.GetEndPoint(1),
				DimDirection = openingData.vecdoorWin.Negate(),
				IsDimDoor = openingData.IsDoor,
				Opening = openingData.WDInstance,
				GridLines = openingDimGridLine
			};
		}

		private List<Line> GetOpeningDimGridLine(Line openingLine)
		{
			Line line = null;
			Line line2 = null;
			XYZ xyz = openingLine.Evaluate(0.5, true);
			XYZ direction = openingLine.Direction;
			double num = double.MaxValue;
			double num2 = double.MaxValue;
			foreach (GridGroupDataEx gridGroupDataEx in this.m_lstGridGroup)
			{
				if (DimPublicFunc.IsParallel(gridGroupDataEx.VecGridNum, direction))
				{
					foreach (Line line3 in gridGroupDataEx.LstLine)
					{
						Line line4 = DimPublicFunc.ChangeLineElevation(line3, xyz.Z);
						XYZ xyz2 = Geometry.IntersectWithTwoCurves(openingLine, line4, xyz, true, false, null);
						if (xyz2 != null)
						{
							XYZ xyz3 = (xyz2 - xyz).Normalize();
							double num3 = xyz2.DistanceTo(xyz);
							if (Geometry.IsEqual(direction, xyz3))
							{
								if (line == null || Geometry.LessThan(num3, num))
								{
									line = line3;
									num = num3;
								}
							}
							else if (line2 == null || Geometry.LessThan(num3, num2))
							{
								line2 = line3;
								num2 = num3;
							}
						}
					}
				}
			}
			if (line == null && line2 == null)
			{
				return null;
			}
			List<Line> list = new List<Line>();
			if (line == null)
			{
				if (line2 == null)
				{
					return null;
				}
				list.Add(line2);
			}
			else if (line2 == null)
			{
				list.Add(line);
			}
			else
			{
				Line line5 = DimPublicFunc.ChangeLineElevation(line, xyz.Z);
				Line line6 = DimPublicFunc.ChangeLineElevation(line2, xyz.Z);
				XYZ xyz4 = Geometry.IntersectWithTwoCurves(openingLine, line5, xyz, true, false, null);
				XYZ xyz5 = Geometry.IntersectWithTwoCurves(openingLine, line6, xyz, true, false, null);
				XYZ xyz6 = Geometry.CalculatMidPoint(xyz4, xyz5);
				if (Geometry.Is_Point_OnSegment(openingLine.GetEndPoint(0), openingLine.GetEndPoint(1), xyz6, 1E-09))
				{
					list.Add(line);
					list.Add(line2);
				}
				else if (xyz4.DistanceTo(xyz) < xyz5.DistanceTo(xyz))
				{
					list.Add(line);
				}
				else
				{
					list.Add(line2);
				}
			}
			return list;
		}

		private List<List<WallDataEx>> GroupWallData()
		{
			List<WallDataEx> list = new List<WallDataEx>();
			foreach (WallDataEx wallDataEx in this.m_lstInWallData)
			{
				if (wallDataEx.ProfileLine is Line && wallDataEx.WallWindows != null && wallDataEx.WallWindows.Count > 0)
				{
					list.Add(wallDataEx);
				}
			}
			foreach (WallDataEx wallDataEx2 in this.m_lstOutWallData)
			{
				if (wallDataEx2.ProfileLine is Line && wallDataEx2.WallWindows != null && wallDataEx2.WallWindows.Count > 0)
				{
					list.Add(wallDataEx2);
				}
			}
			List<List<WallDataEx>> list2 = new List<List<WallDataEx>>();
			for (int i = 0; i < list.Count; i++)
			{
				WallDataEx wallDataEx3 = list[i];
				List<WallDataEx> list3 = new List<WallDataEx>();
				list3.Add(wallDataEx3);
				for (int j = i + 1; j < list.Count; j++)
				{
					WallDataEx wallDataEx4 = list[j];
					if (this.IsTwoWallOnOneLine(wallDataEx3, wallDataEx4))
					{
						list3.Add(wallDataEx4);
						list.RemoveAt(j);
						j--;
					}
				}
				list2.Add(list3);
			}
			return list2;
		}

		private List<WallDataEx> GetWallDataAtPoint(XYZ pt, double dRadius)
		{
			List<WallDataEx> list = new List<WallDataEx>();
			foreach (WallDataEx wallDataEx in this.m_lstInWallData)
			{
				Line line = wallDataEx.ProfileLine as Line;
				if (!(line == null))
				{
					line = DimPublicFunc.ChangeLineElevation(line, pt.Z);
					XYZ endPoint = line.GetEndPoint(0);
					XYZ endPoint2 = line.GetEndPoint(1);
					if (Geometry.LessThan(endPoint.DistanceTo(pt), dRadius) || Geometry.LessThan(endPoint2.DistanceTo(pt), dRadius))
					{
						list.Add(wallDataEx);
					}
				}
			}
			return list;
		}

		private bool IsGroupGridLines(List<Line> lstGridLine1, List<Line> lstGridLine2)
		{
			if (lstGridLine1.Count == 1)
			{
				if (lstGridLine2.Count == 1)
				{
					return this.IsSameLine(lstGridLine1[0], lstGridLine2[0]);
				}
				if (lstGridLine2.Count == 2)
				{
					return this.IsSameLine(lstGridLine1[0], lstGridLine2[0]) || this.IsSameLine(lstGridLine1[0], lstGridLine2[1]);
				}
			}
			else if (lstGridLine1.Count == 2)
			{
				if (lstGridLine2.Count == 1)
				{
					return this.IsSameLine(lstGridLine1[0], lstGridLine2[0]) || this.IsSameLine(lstGridLine1[1], lstGridLine2[0]);
				}
				if (lstGridLine2.Count == 2)
				{
					return this.IsSameLine(lstGridLine1[0], lstGridLine2[0]) || this.IsSameLine(lstGridLine1[1], lstGridLine2[1]) || this.IsSameLine(lstGridLine1[0], lstGridLine2[1]) || this.IsSameLine(lstGridLine1[1], lstGridLine2[0]);
				}
			}
			return false;
		}

		private bool IsSameLine(Line line1, Line line2)
		{
			XYZ endPoint = line1.GetEndPoint(0);
			XYZ endPoint2 = line1.GetEndPoint(1);
			XYZ endPoint3 = line2.GetEndPoint(0);
			XYZ endPoint4 = line2.GetEndPoint(1);
			return Geometry.IsEqual(endPoint, endPoint3) && Geometry.IsEqual(endPoint2, endPoint4);
		}

		private bool IsLinkLine(Line line1, Line line2)
		{
			if (!DimPublicFunc.IsParallel(line1.Direction, line2.Direction))
			{
				return false;
			}
			XYZ endPoint = line1.GetEndPoint(0);
			XYZ endPoint2 = line1.GetEndPoint(1);
			XYZ endPoint3 = line2.GetEndPoint(0);
			XYZ endPoint4 = line2.GetEndPoint(1);
			XYZ xyz = Geometry.CalculateFootPoint(endPoint, endPoint2, endPoint3);
			XYZ xyz2 = Geometry.CalculateFootPoint(endPoint, endPoint2, endPoint4);
			if (Geometry.LessThan(DrawInWallDWDim.m_dPointOverlapDist, xyz.DistanceTo(endPoint3)) || Geometry.LessThan(DrawInWallDWDim.m_dPointOverlapDist, xyz2.DistanceTo(endPoint4)))
			{
				return false;
			}
			double fourPointMaxDist = DrawInWallDWDim.GetFourPointMaxDist(endPoint, endPoint2, xyz, xyz2);
			return !Geometry.LessThan(line1.Length + line2.Length, fourPointMaxDist, DrawInWallDWDim.m_dPointOverlapDist);
		}

		private bool IsTwoWallOnOneLine(WallDataEx wallData1, WallDataEx wallData2)
		{
			if (wallData1.IsOutWall != wallData2.IsOutWall)
			{
				return false;
			}
			if (wallData1.OutLine == null || wallData1.InLine == null || wallData2.OutLine == null || wallData2.InLine == null)
			{
				return false;
			}
			Line line = wallData1.OutLine as Line;
			Line line2 = wallData1.InLine as Line;
			if (line == null || line2 == null)
			{
				return false;
			}
			Line line3 = wallData2.OutLine as Line;
			Line line4 = wallData2.InLine as Line;
			if (line3 == null || line4 == null)
			{
				return false;
			}
			if (!DimPublicFunc.IsParallel(line2.Direction, line4.Direction))
			{
				return false;
			}
			XYZ xyz = new XYZ(0.0, 0.0, 0.0);
			XYZ xyz2 = Geometry.RotateTo(line2.Direction, Math.PI*.5, XYZ.BasisZ);
			Line line5 = Line.CreateBound(xyz, xyz + xyz2 * 1000.0);
			line = DimPublicFunc.ChangeLineElevation(line, xyz.Z);
			line3 = DimPublicFunc.ChangeLineElevation(line3, xyz.Z);
			line2 = DimPublicFunc.ChangeLineElevation(line2, xyz.Z);
			line4 = DimPublicFunc.ChangeLineElevation(line4, xyz.Z);
			XYZ xyz3 = Geometry.IntersectWithTwoCurves(line5, line, xyz, true, true, null);
			XYZ xyz4 = Geometry.IntersectWithTwoCurves(line5, line3, xyz, true, true, null);
			XYZ xyz5 = Geometry.IntersectWithTwoCurves(line5, line2, xyz, true, true, null);
			XYZ xyz6 = Geometry.IntersectWithTwoCurves(line5, line4, xyz, true, true, null);
			if (xyz3 == null || xyz4 == null || xyz5 == null || xyz6 == null)
			{
				return false;
			}
			double fourPointMaxDist = DrawInWallDWDim.GetFourPointMaxDist(xyz5, xyz6, xyz3, xyz4);
			double num = xyz5.DistanceTo(xyz3);
			double num2 = xyz6.DistanceTo(xyz4);
			return Geometry.LessThan(fourPointMaxDist, num + num2);
		}

		private bool GroupWallIntersectGrid(List<WallDataEx> lstWallData)
		{
			foreach (WallDataEx wallDataEx in lstWallData)
			{
				foreach (DoorWinDataEx doorWinDataEx in wallDataEx.WallWindows)
				{
					if (!(doorWinDataEx.doorWinLine == null))
					{
						List<Line> openingDimGridLine = this.GetOpeningDimGridLine(doorWinDataEx.doorWinLine);
						if (openingDimGridLine != null && openingDimGridLine.Count > 0)
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		private static void SortOpeningDims(List<OpeningDimItem> lstDim, XYZ vtSort)
		{
			for (int i = 0; i < lstDim.Count - 1; i++)
			{
				XYZ xyz = Geometry.CalculatMidPoint(lstDim[i].DimPoint1, lstDim[i].DimPoint2);
				for (int j = i + 1; j < lstDim.Count; j++)
				{
					XYZ xyz2 = Geometry.CalculatMidPoint(lstDim[j].DimPoint1, lstDim[j].DimPoint2);
					if (!Geometry.IsEqual((xyz2 - xyz).Normalize(), vtSort))
					{
						OpeningDimItem value = lstDim[i];
						lstDim[i] = lstDim[j];
						lstDim[j] = value;
						xyz = xyz2;
					}
				}
			}
		}

		private static double GetFourPointMaxDist(XYZ pt1, XYZ pt2, XYZ pt3, XYZ pt4)
		{
			List<XYZ> list = new List<XYZ>();
			list.Add(pt1);
			list.Add(pt2);
			list.Add(pt3);
			list.Add(pt4);
			XYZ vtLine = (pt1 - pt2).Normalize();
			DrawInWallDWDim.SortPoints(list, vtLine);
			return list[0].DistanceTo(list[3]);
		}

		private static void SortPoints(List<XYZ> lstPt, XYZ vtLine)
		{
			for (int i = 0; i < lstPt.Count - 1; i++)
			{
				for (int j = i + 1; j < lstPt.Count; j++)
				{
					XYZ xyz = (lstPt[j] - lstPt[i]).Normalize();
					if (!Geometry.LessThan(xyz.GetLength(), 1E-05) && !Geometry.IsEqual(vtLine, xyz))
					{
						XYZ value = lstPt[i];
						lstPt[i] = lstPt[j];
						lstPt[j] = value;
					}
				}
			}
		}

		private Document m_doc;

		private bool m_isDimOutWall;

		private static double m_dPointOverlapDist = AssistFunc.mmToFeet(1.0);

		private static double m_dSizeLineOffset = AssistFunc.mmToFeet(600.0);

		private List<WallDataEx> m_lstInWallData;

		private List<WallDataEx> m_lstOutWallData;

		private List<ElementId> m_lstOutOpeningId;

		private List<GridGroupDataEx> m_lstGridGroup;

		private List<LeaderDimension> m_lstLeaderDim;

		private List<ElementId> m_lstDimCrossWallId;
	}
}
